﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace CodeGen.TS
{
    public static class AssemblyLoader
    {
        static AssemblyLoader()
        {
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }

        static Dictionary<string, Assembly> PathAssemblyMapping { get; set; }
        static string Directory;

        

        public static Assembly GetAssembly(string fileName)
        {
            if (PathAssemblyMapping == null)
                PathAssemblyMapping = new Dictionary<string, Assembly>();
            else
            {
                if (PathAssemblyMapping.ContainsKey(fileName))
                    return PathAssemblyMapping[fileName];
            }
            Directory = System.IO.Path.GetDirectoryName(fileName);
            byte[] content = System.IO.File.ReadAllBytes(fileName);
            var assembly = Assembly.Load(content);
            PathAssemblyMapping.Add(fileName, assembly);
            return assembly;
        }

        static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            string name = args.Name.Substring(0, args.Name.IndexOf(",", StringComparison.Ordinal));
            string itemFileName = System.IO.Path.Combine(Directory, name + ".dll");
            if (System.IO.File.Exists(itemFileName))
            {
                byte[] assContent = System.IO.File.ReadAllBytes(itemFileName);
                Logger.LogMessage("Assembly \"{0}\" loaded", name);
                return Assembly.Load(assContent);

            }
            return Assembly.Load(args.Name);
        }
    }

    public static class AssemblyHelper
    {

        public static Type GetTypeByName(this Assembly assembly, string name,  bool fullQualified)
        {
            if (fullQualified)
                return assembly.GetType(name, false); //Using .Net Implementation is likely to be faster then looping through all types

            var types = assembly.GetTypes();
            foreach (var type in types)
            {
                
                string typeName = type.FullName;

                if (typeName == name)
                    return type;
                if (!fullQualified)
                {
                    if (typeName.Contains("."))
                    {
                        typeName = type.FullName.Substring(type.FullName.LastIndexOf(".") + 1);
                    }
                    if (typeName == name)
                        return type;
                }
                
            }
            return null;
        }
    }
}
